package com.crhms.seabow.security;


import com.crhms.seabow.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint;

/**
 * 注意  protected void configure(AuthenticationManagerBuilder auth) throws Exception { 方法中
 * 密码校验具有加密和不加密两种情况，所谓加密是值，前台传递来的是明文，后台被比较的-从数据库取出来的密码是明文加密后存储的，
 * 这样需要将前台明文密码加密后和数据库存储的密码进行比较，
 * 需要结合 com.bestcxx.stu.springbootsecuritydb.security.service.CustomUserService 类中的注释进行理解
 * @author wj
 *
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private MyLogoutHandler logoutHandler;


    @Autowired
    private ForbiddenEntryPoint forbiddenEntryPoint;
    /**
     * 配置 特殊权限-特殊路径
     * 配置 任意权限-剩余路径
     * 配置 登陆页-用户名、密码-登陆失败页-不需要权限
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/**").permitAll()
                //需要权限ROLE_COMMON 才可以访问的路径   <a th:href="@{/common/test}">去test.html</a>
                //.antMatchers("/common/**").hasRole("COMMON")
                // 只有具有任意的某个权限就可以访问其他访问-没有权限还是无法访问的
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                // 登录成功
                .successHandler(loginSuccessHandler)
                // 登录失败
                .failureHandler(loginFailureHandler).permitAll()
                .and()
                // 未登录请求资源
                .exceptionHandling().authenticationEntryPoint(forbiddenEntryPoint)
                .and()
                // 允许任何请求（不管有没有权限以及拥有何种权限）登出
                .logout().logoutSuccessHandler(logoutHandler)
                .and()
                .csrf().disable();;

    }


    @Bean
    UserDetailsService customUserService() {
        return new CustomUserDetailsService();
    }

    /**
     * 用户登陆校验
     * 调用了customUserService()，内部覆盖重写了 UserDetailsService.loadUserByUsername,需返回 配置了权限的UserDetails的子类对象
     * 作为登陆用户权限配置的依据
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 对于数据库密码加密的情况
        auth.userDetailsService(customUserService()).passwordEncoder(new PasswordEncoder(){
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String)rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(MD5Util.encode((String)rawPassword));
            }

        });
    }

}
